# -*- coding: utf-8 -*-
# @Time    : 2020/12/14 14:04
# @Author  : Guo_Zhanyu
# @File    : OmegaGo.py
from BoardBasics import *
from aiGzy2 import *
from PyQt5.QtCore import QTimer
import Choose
import requests


class BoardClient(BoardGUI):
    """
    Client
    """
    def __init__(self, lines):
        """
        Generate and Update a GUI, Connected with Server and Update timely.

        :param lines: The dimension of the board.
        """
        super(BoardClient, self).__init__(lines)
        self.who_am_i = None  # Who am i?
        self.ai = None        # AI class
        self.id = 0           # Player's id
        self.state = 0        # Game's state

        # 选择颜色的窗口
        self.Choose = QMainWindow()
        self.ChooseUI = Choose.Ui_MainWindow()
        self.ChooseUI.setupUi(self.Choose)
        self.ChooseUI.pushButton.clicked.connect(self.chooseBlack)
        self.ChooseUI.pushButton_2.clicked.connect(self.chooseWhite)
        self.ChooseUI.pushButton_3.clicked.connect(self.chooseYellow)
        self.Choose.show()

        # 定时器，定时与服务器更新棋盘
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.operate)

        # 玩家 or AI模式
        self.mode = 0
        self.MainWindowUI.pushButton_2.clicked.connect(self.setPlayerMode)
        self.MainWindowUI.pushButton_3.clicked.connect(self.setAIMode)

        pass

    def chooseBlack(self):
        """
        Callback of ChooseUI black button.

        :return: None
        """
        self.who_am_i = BLACK_CHESSMAN
        self.ai = AI(self._lines, self.who_am_i)
        self.setWindowTitle('Omega Black')
        self.show()
        self.Choose.close()
        pass

    def chooseWhite(self):
        """
        Callback of ChooseUI white button.

        :return: None
        """
        self.who_am_i = WHITE_CHESSMAN
        self.ai = AI(self._lines, self.who_am_i)
        self.setWindowTitle('Omega White')
        self.show()
        self.Choose.close()
        pass

    def chooseYellow(self):
        """
        Callback of ChooseUI yellow button.

        :return: None
        """
        self.who_am_i = YELLOW_CHESSMAN
        self.ai = AI(self._lines, self.who_am_i)
        self.setWindowTitle('Omega Yellow')
        self.show()
        self.Choose.close()
        pass

    def setPlayerMode(self):
        """
        Callback of player mode.

        :return: None
        """
        self.mode = 0
        pass

    def setAIMode(self):
        """
        Callback of AI mode.

        :return: None
        """
        self.mode = 1
        pass

    def regret(self):
        """
        Callback of regret button.

        :return: None
        """
        # 如果有步可以悔棋
        # if self.board.history:
        #     board = self.board.getBoard()
        #     board[self.board.last.y][self.board.last.x] = 0
        #     self.board.setBoard(board)
        #     self.board.cur_runner = self.board.getNextRunner(self.board.cur_runner)
        #
        #     self.board.history.pop(-1)
        #     if self.board.history:
        #         self.board.last = self.board.history[-1]
        #     else:
        #         self.board.last = None
        #
        #     requests.get(self.url + 'rest/regret')
        #     self.update()
        # else:
        #     print('Can not regret')
        #     pass

        pass

    def mousePressEvent(self, event):
        """
        Mouse press function.

        :param event: mouse event
        :return: None
        """
        if event.button() == Qt.LeftButton:
            if self.state not in [2, 3] and self.board.cur_runner.name == self.who_am_i.name and self.mode == 0:
                # 如果没有胜者、当前轮次、玩家模式
                mouse_pos = [event.pos().x(), event.pos().y()]
                # 得到鼠标的棋盘位置
                click_point = self.getClickPoint(mouse_pos)

                # 在棋盘范围内
                if click_point is not None:
                    if self.board.canDrop(click_point):
                        self.board.drop(self.board.cur_runner, click_point)

                        self.postRestBoard(click_point.x, click_point.y)
                        pass
                    pass
                else:
                    print('超过棋盘范围...')
                    pass
                self.update()
                pass
            pass
        pass

    def paintEvent(self, event):
        """
        Update graphically

        :param event: paint event
        :return: None
        """
        qp = QPainter(self)
        qp.begin(self)
        # 抗锯齿
        qp.setRenderHint(QPainter.Antialiasing)
        self.drawBoard(qp)  # 画棋盘
        self.drawStones(qp)  # 画棋子

        if self.state == 3:
            self.Dialog.show()
            pass

        qp.end()
        pass

    def rerun(self):
        """
        Callback of Dialog OK button

        :return: None
        """
        # 提交重置棋盘申请
        self.postRestBoard(-1, -1)
        # 更新游戏状态
        self.getRestPlay()  # state <- new_state
        pass

    def notrerun(self):
        """
        Callback of Dialog Cancel button

        :return: None
        """
        # 没想好不继续要进行什么处理，暂且重开同样操作
        self.postRestBoard(-1, -1)
        # 更新游戏状态
        self.getRestPlay()  # state <- new_state
        pass

    def closeEvent(self, event):
        """
        Click on X (exit) callback.

        :param event:
        :return: None
        """
        # 提交重置棋盘申请
        self.postRestBoard(-1, -1)
        pass

    def buttonFunc(self, ui):
        """
        Callback of MainWindow connect button

        :param ui: current ui -> MainWindow()
        :return: None
        """
        dataIn = ui.lineEdit.text()
        if dataIn != '':
            self.url = f'http://{dataIn}:5000/'
            pass
        ui.label_3.setText(self.url)
        self.postRestPlayer()
        self.getRestPlayer()

        # 开始定时器，T = 100ms
        self.timer.start(100)
        pass

    def operate(self):
        """
        Timer.

        :return: None
        """
        try:
            # 更新棋盘
            self.getRestBoard()  # board <- new_board

            # 更新信息
            self.getRestPlayer()  # id, board.players

            # 更新当前轮次/最后一步
            self.getRestActionLast()  # current_runner, last <- new*

            # 更新游戏状态
            self.getRestPlay()  # state <- new_state

            # AI下子
            if self.mode == 1 and self.board.cur_runner.name == self.who_am_i.name and self.state not in [2, 3]:
                AI_point = self.ai.AI_drop()
                self.board.drop(self.who_am_i, AI_point)
                self.board.cur_runner = self.board.getNextRunner(self.board.cur_runner)

                # 提交
                self.postRestBoard(AI_point.x, AI_point.y)
                pass

            # 更新棋盘
            self.getRestBoard()     # board <- new_board

            # 更新当前轮次/最后一步
            self.getRestActionLast()  # current_runner, last <- new*

            # 更新游戏状态
            self.getRestPlay()  # state <- new_state
            self.update()
        except Exception as e:
            self.MainWindowUI.label_3.setText('连接失败...')
            print(e)
            self.timer.stop()
        pass

    def getRestPlay(self):
        """
        Get game's state.

        :return: None
        """
        r = requests.get(self.url + 'rest/play')
        rev = r.json()
        # print(rev, type(rev))
        self.state = rev
        pass

    def postRestPlayer(self):
        """
        postRestPlayer

        :return: None
        """
        try:
            post = dict()
            post['ip'] = self.getLocalIP()
            post['color'] = self.who_am_i.name
            r1 = requests.post(self.url + 'rest/player', data=post)
            rev = r1.json()
            # print(rev, type(rev))
        except Exception as e:
            self.MainWindowUI.label_3.setText('连接失败...')
            print(e)
        pass

    def getRestPlayer(self):
        """
        Get id.

        :return: None
        """
        r = requests.get(self.url + 'rest/player')
        rev = r.json()
        # print(rev, type(rev))
        self.id = rev[self.who_am_i.name]
        self.board.players = len(rev.keys())
        pass

    def getRestBoard(self):
        """
        Get Board from server.

        :return: None
        """
        r = requests.get(self.url + 'rest/board')
        rev = r.json()
        # print(rev, type(rev))
        new_board = rev['board']
        self.board.setBoard(new_board)
        self.ai.setBoard(new_board)
        pass

    def getRestActionLast(self):
        """
        Get last info.

        :return: None
        """
        r = requests.get(self.url + 'rest/action/last')
        rev = r.json()
        # print(rev, type(rev))
        # error
        if isinstance(rev, str):
            self.board.cur_runner = BLACK_CHESSMAN
        else:
            # 无敌！！！
            # print(((rev['playerid']) % self.board.players) + 1)
            if self.board.players != 1:
                if ((rev['playerid']) % self.board.players) + 1 == self.id:
                    self.board.cur_runner = self.who_am_i
                else:
                    self.board.cur_runner = self.board.getNextRunner(self.who_am_i)
                    pass
                # print(self.board.cur_runner.name)

            self.board.last = Point(rev['x'], rev['y'])
            pass
        pass

    def postRestBoard(self, x, y):
        """
        Post Board.

        :param x: new x -> int()
        :param y: new y -> int()
        :return: None
        """
        send = dict()
        send['id'] = self.id
        send['x'] = x
        send['y'] = y
        send['color'] = self.who_am_i.name
        r = requests.post(self.url + 'rest/board', data=send)
        rev = r.json()
        # print(rev, type(rev))
        pass

    pass


def main():
    client = QApplication(sys.argv)
    board_client = BoardClient(LINES)
    sys.exit(client.exec_())
    pass


if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        print(e)
        pass
    pass
